package com.ying.dogying;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author 李华明
 * @Date 2020/5/28
 */
public class DogGenerator {
    private static DogGenerator single = null;
    // 数据库类型
    private final DbType dbType = DbType.MYSQL;
    // 数据库连接信息
    private final String dbUrl = "jdbc:mysql://123.56.46.23:3306/dog-ying?useUnicode=true&characterEncoding=UTF8&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&autoReconnectForPools=true&allowMultiQueries=true";
    private final String driver = "com.mysql.cj.jdbc.Driver";
    private final String userName = "root";
    private final String password = "Yy5213344.";
    // 作者名、生成路径、指定包名、指定生成的表名
    private final String author = "李华明";
    private final String outputUrl = System.getProperty("user.dir") + "\\src\\main\\java";
    private final String mapperOutputUrl = System.getProperty("user.dir") + "\\src\\main\\resources\\mapper\\";
    private static final String packageName = "com.ying.dogying";
    private static final String[] tableNames = new String[]{
            "im_user_message"
    };

    // 启动
    public static void main(String[] args) {
        DogGenerator generator = DogGenerator.getSingle();
        generator.generatorByTableNames(packageName, tableNames);
    }
    private DogGenerator() {
        super();
    }
    private static DogGenerator getSingle() {
        if (null == single) {
            single = new DogGenerator();
        }
        return single;
    }

    // 集成
    private void generatorByTableNames(String packageName, String... tableNames) {
        // 配置.数据源
        DataSourceConfig dataSourceConfig = getDataSourceConfig();
        // 配置.策略
        StrategyConfig strategyConfig = getStrategyConfig(tableNames);
        // 配置.包名
        PackageConfig packageConfig = getPackageConfig(packageName);
        // 配置.全局
        GlobalConfig globalConfig = getGlobalConfig();
        // 配置.自定义
        InjectionConfig injectionConfig = getCustomConfig();
        // 配置.模板
        TemplateConfig templateConfig = getTemplateConfig();
        // 自动生成
        autoGenerator(dataSourceConfig, strategyConfig, packageConfig, globalConfig, injectionConfig, templateConfig);
    }

    /**
     * 数据源
     * @return DataSourceConfig
     */
    private DataSourceConfig getDataSourceConfig() {
        return new DataSourceConfig()
                .setDbType(dbType)
                .setUrl(dbUrl)
                .setDriverName(driver)
                .setUsername(userName)
                .setPassword(password);
    }

    /**
     * 策略
     * @param tableNames
     * @return StrategyConfig
     */
    private StrategyConfig getStrategyConfig(String[] tableNames) {
        return new StrategyConfig()
                // 全局大写命名 ORACLE 需要注意
                .setCapitalMode(true)
                // 表名生成策略
                .setNaming(NamingStrategy.underline_to_camel)
                // 数据库字段映射到实体中的命名策略
                // .setColumnNaming(NamingStrategy.underline_to_camel)
                // 使用 lombok，默认为：false
                .setEntityLombokModel(true)
                // 生成 @RestController 控制器
                .setRestControllerStyle(true)
                // 自定义继承的 entity 类全称，带包名（你自己的父类实体,没有就不用设置!）
                // .setSuperEntityClass(BaseEntity.class)
                // 自定义继承的 controller 类全称，带包名（你自己的父类控制器,没有就不用设置!）
                // .setSuperControllerClass(BaseController.class)
                // 驼峰转连字符
                .setControllerMappingHyphenStyle(true)
                // 是否生成实体类时，生成字段注释
                .setEntityTableFieldAnnotationEnable(true)
                //需要生成的的表名，多个表名传数组
                .setInclude(tableNames);
                // 去除表名前缀
                // .setTablePrefix(pc.getModuleName() + "_");
    }

    /**
     * 包名
     * @param packageName
     * @return PackageConfig
     */
    private PackageConfig getPackageConfig(String packageName) {
        return new PackageConfig()
                .setParent(packageName)
                .setController("controller")
                .setService("service")
                .setServiceImpl("service.impl")
                .setMapper("dao")
                .setEntity("entity");
                // .setXml("mapper");
    }

    /**
     * 全局
     * @return GlobalConfig
     */
    private GlobalConfig getGlobalConfig() {
        return new GlobalConfig()
                .setBaseColumnList(true)
                .setBaseResultMap(true)
                .setActiveRecord(false)
                // 设置作者名
                .setAuthor(author)
                // 设置生成路径
                .setOutputDir(outputUrl)
                // 设置是否覆盖
                .setFileOverride(true)
                // 生成完成是否打开
                .setOpen(false)
                // 设置是否生成 swagger2 的注解
                // .setSwagger2(true)
                // 设置 Service 的后缀名
                .setServiceName("%sService")
                // 设置 Mapper / Dao 的后缀名
                .setMapperName("%sDao");
    }

    private InjectionConfig getCustomConfig() {
        // 自定义配置
        InjectionConfig customConfig = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        // 自定义xml的存放路径
        List<FileOutConfig> focList = new ArrayList<>();
        focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义Mapper.xml文件存放的路径
                return mapperOutputUrl + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        return customConfig.setFileOutConfigList(focList);
    }

    private TemplateConfig getTemplateConfig() {
        // 配置生成的资源模板
        return new TemplateConfig()
                //不生成controller
                // templateConfig.setController(null);
                //不生成service
                // templateConfig.setService(null);
                //不生成service实现
                // templateConfig.setServiceImpl(null);
                // 关闭默认 xml 生成，调整生成 至 根目录
                .setXml(null);
    }

    /**
     * 自动生成
     * @param dataSourceConfig 数据源
     * @param strategyConfig 策略
     * @param packageConfig 包名
     * @param globalConfig 全局
     */
    private void autoGenerator(DataSourceConfig dataSourceConfig, StrategyConfig strategyConfig,
                               PackageConfig packageConfig, GlobalConfig globalConfig,
                               InjectionConfig injectionConfig, TemplateConfig templateConfig) {
        new AutoGenerator()
                .setDataSource(dataSourceConfig)
                .setStrategy(strategyConfig)
                .setPackageInfo(packageConfig)
                .setGlobalConfig(globalConfig)
                .setCfg(injectionConfig)
                .setTemplate(templateConfig)
                .setTemplateEngine(new FreemarkerTemplateEngine())
                // 执行
                .execute();
    }
}
